package clases;

import java.util.ArrayList;
import java.util.Enumeration;
import java.util.Hashtable;
import main.Errores;
import main.Global;

/**
  *  4g3nt
  *  Copyright (C) 2008  Carlos Molinero y César Andrés
  *
  *  This program is free software: you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
  *  the Free Software Foundation, either version 3 of the License, or
  *  (at your option) any later version.
  *
  *  This program is distributed in the hope that it will be useful,
  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  *  GNU General Public License for more details.
  *
  *    You should have received a copy of the GNU General Public License
  *    along with this program.  If not, see <http://www.gnu.org/licenses/>.
  *
  */
public class Agente implements Runnable{
    protected String _id;
    private Hashtable _estados = new Hashtable();
    private String _estadoInicial;
    private String _estadoFinal;
    private String _funcionUtilidad;
    private String _funcionCreaccion;
    private String _funcionDestruccion;
    private ArrayList<Transicciones> _transicciones= new ArrayList();
	private BufferEntrada _inputBuffer= new BufferEntrada (10);
	private String _idCelula;
	private boolean _completo=false;
	public void run() {
		
	
		Mensajes mensaje = _inputBuffer.fetch();
		procesaMensaje(mensaje);
		
	}
	public void setCompleto(boolean completo)
	{
		_completo = completo;
	}
	public void insertarMensaje(Mensajes mensaje)
	{	
		_inputBuffer.insertarMensaje(mensaje);
	}
	private void procesaMensaje(Mensajes mensaje)
	{
		Global.escribir("<tr class=\"modo1\"><td>Agente("+_id+","+_idCelula+") procesando:</td><td> "+mensaje.toString()+"</td></tr>");
		switch (mensaje.getID())
		{
		case Mensajes.EMPEZARTRABAJO :
		{
			break;
		}
		case Mensajes.FINALIZARTRABAJO :
		{
			break;
		}
		
		case Mensajes.IDENTIFICACION:
		{
			/**
			 * El agente manda un mensaje de respuesta con su estado final
			 * origen, destino, ....
			 */
			//Mandamos el mensajes si coincide lo que nos piden
			if (mensaje.getFuncionCreaccion().equals(_funcionCreaccion))
			{
			Mensajes mensajes = Mensajes.mensajeRespuestaPeticion(new ParesAC(_id,_idCelula), mensaje.getOrigen(), _funcionCreaccion, tiempoTotal(),_funcionDestruccion); 
			Global.getCelula(_idCelula).sendMessage(mensajes);
			}
			
			break;
		}

		case Mensajes.RESPUESTA :
		{
			break;
		}

		}
		run();
	}
	public void setCelula(String celula)
	{
		_idCelula = celula;
	}
    public String getId()
    {
    		return _id;
    	
    }
    public boolean iqualsID(String id)
    {
    	return _id.equals(id);
    }
    public void setEstado(String estado)
    {
    	if (_estados.get(estado)!=null)
    				Errores.insertar("Estado repetido en el agente "+_id);
    	this._estados.put(estado, new Estado(estado));
    }
    public void setEstadoInicial(String estadoInicial)
    {
    	_estadoInicial = estadoInicial;
    	
    }
    public void setEstadoFinal(String estadoFinal)
    {
    	_estadoFinal = estadoFinal;
    	
    }
    public void setFuncionUtilidad(String funcionUtilidad)
	{
    	_funcionUtilidad = funcionUtilidad;
	}
    public void setId(String id)
    {
    	_id=id;
		Global.setThread(new Thread(this, id));

    }
    public void addTransicciones(Transicciones tr)
    {
    	
    	_transicciones.add(tr);
    }
    
    public void print() {
		 Global.escribir("<li class=\"closed\"><span class=\"folder\">"+_id+"</span>");
		 Global.escribir("<ul>");
			 Global.escribir("<li class=\"closed\"><span class=\"folder\">Estados</span>");
			 Global.escribir("<ul>");
			    Enumeration enumerador = _estados.keys();
			    while (enumerador.hasMoreElements())
			    {
			    	Estado var_estado = (Estado)_estados.get((String)enumerador.nextElement());
			    	var_estado.print();
			    }
				 		
			 Global.escribir("</ul>");
			 Global.escribir("<li>");
			 Global.printFuncion(Global.getFUtilidad(_funcionUtilidad),"Funcion Utilidad",_funcionUtilidad);
			 Global.printFuncion(Global.getFCreaccion(_funcionCreaccion),"Funcion Creaccion",_funcionCreaccion);
			 Global.printFuncion(Global.getFDestruccion(_funcionDestruccion),"Funcion Destruccion",_funcionDestruccion);                         
                         Global.escribir("<li><span class=\"file\">Id="+_id+"</span></li>");
			 if (_estados.get(_estadoInicial)==null) Errores.insertar("Estado inicial del agente "+_id+" no definido");
			 Global.escribir("<li><span class=\"file\">Estado Inicial="+_estadoInicial+"</span></li>");
			 if (_estados.get(_estadoFinal)==null) Errores.insertar("Estado final del agente "+_id+" no definido");
			 Global.escribir("<li><span class=\"file\">Estado Final="+_estadoFinal+"</span></li>");
			 Global.escribir("<li class=\"closed\"><span class=\"folder\">Transicciones</span>");
			 Global.escribir("<ul>");
			 	for (int i = 0; i< _transicciones.size();i++)
			 	{
			 		Transicciones tr = _transicciones.get(i);
			 		if (_estados.get(tr.getEstadoI())==null)  Errores.insertar("Estado inicial de una transicion del agente " + _id + " no existe");
			 		if (_estados.get(tr.getEstadoF())==null)  Errores.insertar("Estado inicial de una transicion del agente " + _id + " no existe");
			 		tr.print();
			 	}
			 Global.escribir("</ul>");
			 Global.escribir("<li>");
		 Global.escribir("</ul>");
		 Global.escribir("<li>");
	}
    public float tiempoTotal()
    {
    	
    	float resultado=0f;
    	for (int i = 0 ; i < _transicciones.size();i++)
    	{
    		resultado+=_transicciones.get(i).getTiempo();
    	}
    	return resultado;
    }
    public void realizaTrabajo()
    {
    	Global.escribir("<li><span class=\"file\">"+_id+" trabajando</span></li>");
    }

    public String getFuncionCreaccion() {
        return _funcionCreaccion;
    }

    public void setFuncionCreaccion(String funcionCreaccion) {
        this._funcionCreaccion = funcionCreaccion;
    }

    public String getFuncionDestruccion() {
        return _funcionDestruccion;
    }

    public void setFuncionDestruccion(String funcionDestruccion) {
        this._funcionDestruccion = funcionDestruccion;
    }
    
}
